package com.ysd.lis.service.qc.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.ysd.common.Result;
import com.ysd.lis.entity.lab.*;
import com.ysd.lis.entity.qc.*;
import com.ysd.lis.mapper.lab.LabInstrSetupMapper;
import com.ysd.lis.mapper.qc.*;
import com.ysd.lis.request.CommonPageDto;
import com.ysd.lis.request.MaterialItemDto;
import com.ysd.lis.service.SysBasDictDetailService;
import com.ysd.lis.service.qc.QcMaterialItemService;
import com.ysd.util.ToolsUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * cold_chain.t_user 服务实现类
 * </p>
 *
 * @author peng
 * @since 2021-10-08
 */
@Service
@Slf4j
public class QcMaterialItemServiceImpl extends ServiceImpl<QcMaterialItemMapper, QcMaterialItem> implements QcMaterialItemService {

    @Autowired
    QcMaterialItemMapper qcMaterialItemMapper;
    @Autowired
    QcMaterialMapper qcMaterialMapper;
    @Autowired
    LabInstrSetupMapper labInstrSetupMapper;
    @Autowired
    QcMaterialItemTargetMapper qcMaterialItemTargetMapper;
    @Autowired
    QcMaterialItemFixedMapper qcMaterialItemFixedMapper;
    @Autowired
    SysBasDictDetailService sysBasDictDetailService;
    @Autowired
    QcMaterialItemResultMapper qcMaterialItemResultMapper;

    @Override
    public Result batchAddMaterialItemList(MaterialItemDto dto) {
        List<QcMaterialItem> materialItemList = dto.getMaterialItemList();
        boolean b = this.saveBatch(materialItemList);
        if(b){
            return Result.succ(1, "添加成功", null);
        }else {
            return Result.fail(400,"添加失败","");
        }
    }

    @Override
    public Result findMaterialItemList(CommonPageDto pageParam) {
        MPJLambdaWrapper<QcMaterialItem> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(QcMaterialItem.class)
                .selectAs("ld", LabItemDict::getItemNo,QcMaterialItem::getItemDictCode)
                .selectAs("ld", LabItemDict::getItemNa,QcMaterialItem::getItemDictName)
                .selectAs("ld", LabItemDict::getItemEnCode,QcMaterialItem::getItemEnCode)
                .selectAs("sup", LabSupplier::getSupplierName,QcMaterialItem::getReagentSupplierName)
                .selectAs("man", LabManufacturer::getManuName,QcMaterialItem::getReagentManuName)
                .leftJoin(LabItemDict.class,"ld",LabItemDict::getId,QcMaterialItem::getItemDictId)
                .leftJoin(LabSupplier.class,"sup",LabSupplier::getId,QcMaterialItem::getReagentSupplier)
                .leftJoin(LabManufacturer.class,"man",LabManufacturer::getId,QcMaterialItem::getReagentManu)
                .eq(QcMaterialItem::getMaterialId,pageParam.getPid())
                .eq(QcMaterialItem::getDelFlag,0)
                .orderByAsc(QcMaterialItem::getSeq);
        List<QcMaterialItem> itemList = qcMaterialItemMapper.selectList(queryWrapper);

        return Result.succ(1, "查询成功", itemList);
    }

    @Override
    public Result findQcInstrItemListByInstrIds(CommonPageDto pageParam) {
        MPJLambdaWrapper<QcMaterialItem> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(QcMaterialItem.class)
                .selectAs("ld", LabItemDict::getItemNo,QcMaterialItem::getItemDictCode)
                .selectAs("ld", LabItemDict::getItemNa,QcMaterialItem::getItemDictName)
                .selectAs("ld", LabItemDict::getItemEnCode,QcMaterialItem::getItemEnCode)
                .selectAs("qm",QcMaterial::getMaterialName, QcMaterialItem::getMaterialName)
                .leftJoin(LabItemDict.class,"ld",LabItemDict::getId,QcMaterialItem::getItemDictId)
                .leftJoin(QcMaterial.class, "qm", QcMaterial::getId, QcMaterialItem::getMaterialId)
                .in(QcMaterialItem::getMaterialId,pageParam.getColumNameList())
                .eq(QcMaterialItem::getDelFlag,0)
                .orderByAsc(QcMaterialItem::getSeq);
        List<QcMaterialItem> itemList = qcMaterialItemMapper.selectList(queryWrapper);

        // 写入统计信息
        LambdaQueryWrapper<QcMaterialItemResult> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(QcMaterialItemResult::getDelFlag, 0)
                .in(QcMaterialItemResult::getMaterialId, pageParam.getColumNameList())
                .ge(QcMaterialItemResult::getQcDate, new Timestamp(pageParam.QCDateS.getTime()))
                .le(QcMaterialItemResult::getQcDate, new Timestamp(pageParam.QCDateE.getTime()))
                .orderByAsc(QcMaterialItemResult::getQcDate, QcMaterialItemResult::getQcSequence);
        List<QcMaterialItemResult> materialItemResultList = qcMaterialItemResultMapper.selectList(queryWrapper1);
        Map<String, List<QcMaterialItemResult>> collect1 = materialItemResultList.stream().collect(Collectors.groupingBy(QcMaterialItemResult::getMaterialItemId));

        List<QcMaterialItem> resultList =new ArrayList<>();
        itemList.stream().forEach(item -> {
            QcMaterialItem qcMaterialItem = new QcMaterialItem();
            BeanUtil.copyProperties(item, qcMaterialItem);
            if (collect1.containsKey(item.getId())) {
                List<QcMaterialItemResult> list = collect1.get(item.getId());
                long count = list.stream().filter(QcMaterialItemResult::getIsOutControl).count();
                qcMaterialItem.setOutControlCount((int) count);
                StringBuilder stringBuilder = new StringBuilder();
                list.stream().filter(QcMaterialItemResult::getIsOutControl).forEach(item1 -> {
                    stringBuilder.append("<br/>").append("质控物:"+item.getMaterialName()).append("日期:" + DataFormart2(item1.getQcDate()))
                            .append("次数:" + item1.getQcSequence()).append("失控规则:"+ item1.getOutControlRules()).toString();
                });
                qcMaterialItem.setOutControlInfo(stringBuilder.toString());
                long count1 = list.stream().filter(QcMaterialItemResult::getIsAlarm).count();
                qcMaterialItem.setAlarmCount((int) count1);
                StringBuilder stringBuilder1 = new StringBuilder();
                list.stream().filter(QcMaterialItemResult::getIsAlarm).forEach(item1 -> {
                    stringBuilder1.append("<br/>").append("质控物:"+item.getMaterialName()).append("日期:" + DataFormart2(item1.getQcDate()))
                            .append("次数:" + item1.getQcSequence()).append("警告规则:"+ item1.getOutControlRules()).toString();
                });
                qcMaterialItem.setAlarmInfo(stringBuilder1.toString());
            }
            resultList.add(qcMaterialItem);
        });
        Map<String, List<QcMaterialItem>> resultMap = resultList.stream().collect(Collectors.groupingBy(QcMaterialItem::getItemDictId));
        List<QcMaterialItem> resultData = new ArrayList<>();
        resultMap.forEach((key, value) -> {
            QcMaterialItem qcMaterialItem = value.get(0);
            if (value.size() > 1) {
                final AtomicInteger outControlCount = new AtomicInteger(0);
                StringBuilder ji = new StringBuilder();
                StringBuilder jii = new StringBuilder();
                final AtomicInteger alarmCount = new AtomicInteger(0);
                value.stream().forEach(item -> {
                    if (ObjectUtil.isNotEmpty(item.getOutControlInfo())) {
                        outControlCount.getAndAdd(item.getOutControlCount());
                        ji.append(item.getOutControlInfo());
                    }
                    if (ObjectUtil.isNotEmpty(item.getAlarmCount())) {
                        alarmCount.getAndAdd(item.getAlarmCount());
                        jii.append(item.getAlarmInfo());
                    }
                });
                qcMaterialItem.setOutControlCount(outControlCount.get());
                qcMaterialItem.setOutControlInfo(ji.toString());
                qcMaterialItem.setAlarmCount(alarmCount.get());
                qcMaterialItem.setAlarmInfo(jii.toString());
            }
            resultData.add(qcMaterialItem);
        });
        List<QcMaterialItem> collect = resultData.stream().sorted(Comparator.comparing(QcMaterialItem::getSeq)).collect(Collectors.toList());
        return Result.succ(1, "查询成功", collect);
    }

    @Override
    public Result batchDeleteMaterialItemList(MaterialItemDto dto) {
        List<QcMaterialItem> qcMaterialItemList = dto.getMaterialItemList();
        List<String> dlids = qcMaterialItemList.stream().filter(a->a.getItemDefine().equals("dl")).map(QcMaterialItem::getId).collect(Collectors.toList());
        if(ToolsUtils.isNotEmpty(dlids)){
            //根据质控物项目IDs查询质控项目下是否有质控靶值
            LambdaQueryWrapper<QcMaterialItemTarget> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(QcMaterialItemTarget::getDelFlag,0);
            queryWrapper.in(QcMaterialItemTarget::getMaterialItemId,dlids);
            int cnt = qcMaterialItemTargetMapper.selectCount(queryWrapper);
            if(cnt>0){
                return Result.succ(1, "质控项目下有靶值设定，不能删除", null);
            }
        }
        List<String> dxids = qcMaterialItemList.stream().filter(a->a.getItemDefine().equals("dx")).map(QcMaterialItem::getId).collect(Collectors.toList());
        if(ToolsUtils.isNotEmpty(dxids)){
            //根据质控物项目IDs查询质控项目下是否有质控靶值
            LambdaQueryWrapper<QcMaterialItemFixed> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(QcMaterialItemFixed::getDelFlag,0);
            queryWrapper1.in(QcMaterialItemFixed::getMaterialItemId,dxids);
            int cnt1 = qcMaterialItemFixedMapper.selectCount(queryWrapper1);
            if(cnt1>0){
                return Result.succ(1, "质控项目下有定性设定，不能删除", null);
            }
        }

        List<String> allids = qcMaterialItemList.stream().map(QcMaterialItem::getId).collect(Collectors.toList());

        boolean b = this.removeByIds(allids);
        if(b){
            return Result.succ(1, "删除成功", null);
        }else {
            return Result.fail(400,"删除失败","");
        }
    }

    @Override
    public Result editBatchMaterialItem(QcMaterial material) {
        List<QcMaterialItem> materialItemList = material.getMaterialItemList();
        if(CollectionUtils.isNotEmpty(materialItemList)){
            boolean b = this.updateBatchById(materialItemList);
            if (b) {
                return Result.succ(1, "更新成功", null);
            } else {
                return Result.fail("更新失败！");
            }
        }else {
            return Result.succ(1, "更新成功", null);
        }
    }

    @Override
    public Result findMaterialItemTree(CommonPageDto pageParam) {
        //查出所有的质控品
        LambdaQueryWrapper<QcMaterial> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(QcMaterial::getDelFlag,0);
        if(StringUtils.isNotBlank(pageParam.getIsShowAll())){
            //0 查询有效期内得  1显示所有得
            if(pageParam.getIsShowAll().equals("0")){
                queryWrapper.le(QcMaterial::getEnableDate,new Timestamp(new Date().getTime()));
                queryWrapper.ge(QcMaterial::getValidDate,new Timestamp(new Date().getTime()));
                queryWrapper.and(wrapper -> wrapper.isNull(QcMaterial::getStopDate).or().ge(QcMaterial::getStopDate, new Timestamp(new Date().getTime())));

            }
        }
        if(ToolsUtils.isNotEmpty(pageParam.getInstrId())){
            queryWrapper.eq(QcMaterial::getInstrId,pageParam.getInstrId());
        }
        if(ToolsUtils.isNotEmpty(pageParam.getInstrIds())){
            queryWrapper.in(QcMaterial::getInstrId,pageParam.getInstrIds());
        }
        queryWrapper.orderByAsc(QcMaterial::getSeq);
        List<QcMaterial> materialList = qcMaterialMapper.selectList(queryWrapper);
        if(CollectionUtils.isNotEmpty(materialList)){
            //插出细项
            List<String> mIds = materialList.stream().map(QcMaterial::getId).collect(Collectors.toList());
            MPJLambdaWrapper<QcMaterialItem> queryWrapper1 = new MPJLambdaWrapper<>();

            queryWrapper1.selectAll(QcMaterialItem.class)
                    .selectAs("ld", LabItemDict::getItemNo,QcMaterialItem::getItemDictCode)
                    .selectAs("ld", LabItemDict::getItemNa,QcMaterialItem::getItemDictName)
                    .selectAs("ld", LabItemDict::getItemEnCode,QcMaterialItem::getItemEnCode)
                    .selectAs("ld", LabItemDict::getUnit,QcMaterialItem::getUnit)
                    .leftJoin(LabItemDict.class,"ld",LabItemDict::getId,QcMaterialItem::getItemDictId)
                    .in(QcMaterialItem::getMaterialId,mIds)
                    .eq(QcMaterialItem::getDelFlag,0)
                    .orderByAsc(QcMaterialItem::getSeq);

            List<QcMaterialItem> itemList = qcMaterialItemMapper.selectList(queryWrapper1);
            List<Map> iList = new ArrayList<>();
            for(QcMaterialItem materialItem : itemList){
                Map<String,Object> map = new HashMap<>();
                map.put("id",materialItem.getId());
                map.put("code",materialItem.getItemDictCode());
                StringBuffer stringBuffer = new StringBuffer();
                if(StringUtils.isNotBlank(materialItem.getItemEnCode())){
                    stringBuffer.append(materialItem.getItemEnCode()+" ");
                }
                if(StringUtils.isNotBlank(materialItem.getItemDictName())){
                    stringBuffer.append(materialItem.getItemDictName());
                }
                if(StringUtils.isNotBlank(materialItem.getUnit())){
                    stringBuffer.append(" [ "+ materialItem.getUnit()+" ]");
                }
                if(null != materialItem.getEnableDate()){
                    stringBuffer.append("  启用日期 "+ DataFormart(materialItem.getEnableDate()));
                }

                //materialItem.getItemEnCode()+" "+materialItem.getItemDictName()+" [ "+ materialItem.getUnit()+" ] 启用日期 "+ DataFormart(materialItem.getEnableDate())
                map.put("name",stringBuffer.toString());
                map.put("materialId",materialItem.getMaterialId());
                map.put("method",materialItem.getMethod());
                map.put("qcNo",materialList.stream().filter(ma->ma.getId().equals(materialItem.getMaterialId())).findFirst().get().getQcNo());
                map.put("batchNum",materialList.stream().filter(ma->ma.getId().equals(materialItem.getMaterialId())).findFirst().get().getBatchNum());
                map.put("horizontal",materialList.stream().filter(ma->ma.getId().equals(materialItem.getMaterialId())).findFirst().get().getHorizontal());
                map.put("qcItemId",materialItem.getQcItemId());
                map.put("instrId",materialItem.getInstrId());
                map.put("itemDictId",materialItem.getItemDictId());
                map.put("itemDefine",materialItem.getItemDefine());
                map.put("enableDate",DataFormart2(materialList.stream().filter(ma->ma.getId().equals(materialItem.getMaterialId())).findFirst().get().getEnableDate()));
                map.put("type","materialItem");
                map.put("isSearch","0");
                iList.add(map);
            }

            List<Map> mList = new ArrayList<>();
            //查字典
            List<Map<String, Object>> qchorizontals = (List<Map<String, Object>>) sysBasDictDetailService.getSysBasDictList("QCHORIZONTAL").getData();

            for(QcMaterial qcMaterial : materialList){
                Map<String,Object> map = new HashMap<>();
                String horizontalDesc;
                String horizontal = qcMaterial.getHorizontal();
                if(StringUtils.isNotBlank(horizontal)){
                    Map<String, Object> code = qchorizontals.stream().filter(a -> a.get("code").equals(horizontal)).findFirst().orElse(null);
                    if(Objects.nonNull(code)){
                        horizontalDesc = code.get("name").toString();
                    }else {
                        horizontalDesc = horizontal;
                    }
                }else {
                    horizontalDesc = horizontal;
                }

                map.put("id",qcMaterial.getId());
                map.put("code",qcMaterial.getQcNo());
                map.put("name","批号 "+qcMaterial.getBatchNum()+" 水平 "+horizontalDesc+" 启用日期 "+ DataFormart(qcMaterial.getEnableDate())+" 效期 "+DataFormart(qcMaterial.getValidDate()));
                map.put("instrId",qcMaterial.getInstrId());
                map.put("children",iList.stream().filter(item -> item.get("materialId").equals(qcMaterial.getId())).collect(Collectors.toList()));
                map.put("isSearch","1");
                map.put("type","material");
                mList.add(map);
            }

            //获取仪器ID
            List<String> instrIds = materialList.stream().map(QcMaterial::getInstrId).distinct().collect(Collectors.toList());
            LambdaQueryWrapper<LabInstrSetup> queryWrapper2 = new LambdaQueryWrapper<>();
            queryWrapper2.eq(LabInstrSetup::getDelFlag, 0)
                    .in(LabInstrSetup::getId,instrIds)
                    .orderByAsc(LabInstrSetup::getCreateTime);
            if(ToolsUtils.isNotEmpty(pageParam.getPoct())){
                queryWrapper2.eq(LabInstrSetup::getPoct, pageParam.getPoct());
            }
            //查仪器
            List<LabInstrSetup> instrList = labInstrSetupMapper.selectList(queryWrapper2);
            List<Map> eqList = new ArrayList<>();
            for(LabInstrSetup instr : instrList){
                Map<String,Object> map = new HashMap<>();
                map.put("id",instr.getId());
                map.put("code",instr.getInstrCode());
                map.put("name",instr.getInstrName());
                map.put("instrClass",instr.getInstrClass());
                map.put("children",mList.stream().filter(ma->ma.get("instrId").equals(instr.getId())).collect(Collectors.toList()));
                map.put("isSearch","1");
                map.put("type","instr");
                eqList.add(map);
            }
            List<String> classList = instrList.stream().map(LabInstrSetup::getInstrClass).distinct().collect(Collectors.toList());
            //查字典
            List<Map<String, Object>> yqdllist = (List<Map<String, Object>>)sysBasDictDetailService.getSysBasDictList("YQDL").getData();

            List<Map>  returnList = new ArrayList<>();

            for(int i = 0;i<classList.size() ;i++){
                String className = classList.get(i);
                Map<String,Object> map = new HashMap();
                map.put("id",i+1);
                map.put("code",className);
                map.put("name",yqdllist.stream().filter(a->a.get("code").equals(className)).findFirst().get().get("name"));
                map.put("children",eqList.stream().filter(is -> is.get("instrClass").equals(className)).collect(Collectors.toList()));
                map.put("isSearch","1");
                map.put("type","instrClass");
                returnList.add(map);
            }
            return Result.succ(1, "查询成功", returnList);
        }


        return Result.succ(1, "查询成功", null);
    }

    private String DataFormart(Timestamp timestamp){
        return  DateUtil.format(timestamp,"yyyy/MM/dd");
    }
    private String DataFormart2(Timestamp timestamp){
        return  DateUtil.format(timestamp,"yyyy-MM-dd");
    }
}
